package com.zipou.framework.gwt.client.widget.suggest;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import com.google.gwt.user.client.rpc.IsSerializable;
import com.google.gwt.user.client.ui.SuggestOracle;

public class GenericSuggestOracle <T extends IsSerializable> extends SuggestOracle {
	private List<GenericMultiWordSuggestion<T>> suggestions = null;

	@Override
	public void requestSuggestions(Request request, Callback callback)
	{
		Response resp = new Response( matchingPeople( request.getQuery(),
				request.getLimit() ) );

		callback.onSuggestionsReady(request, resp);
	}

	/**
	 * 
	 * @param query The current text being entered into the suggest box
	 * @param limit The maximum number of results to return 
	 * @return A collection of people suggestions that match.
	 */
	public Collection<GenericMultiWordSuggestion<T>> matchingPeople(String query, int limit)
	{
		List<GenericMultiWordSuggestion<T>> matchingPeople = new ArrayList<GenericMultiWordSuggestion<T>>(limit);

		// only begin to search after the user has type two characters
		if ( query.length() >= 2 )
		{
			String prefixToMatch = query.toLowerCase();

			int i = 0;
			int s = suggestions.size();

			// Skip forward over all the names that don't match at the beginning of the array.
			while (i < s && !suggestions.get(i).getDisplayString().toLowerCase().contains(prefixToMatch) )
			{
				i++;
			}

			// Now we are at the start of the block of matching names. Add matching names till we
			// run out of names, stop finding matches, or have enough matches.
			int count = 0;

			while (i < s && suggestions.get(i).getDisplayString().toLowerCase().contains(prefixToMatch) && count < limit) 
			{
				matchingPeople.add( suggestions.get(i) );
				i++;
				count++;
			}

		}

		return matchingPeople;
	}



	/**
	 * @param o 
	 * @return
	 * @see java.util.List#add(java.lang.Object)
	 */
	public boolean add(GenericMultiWordSuggestion<T> o)
	{
		if ( suggestions == null )
		{
			suggestions = new ArrayList<GenericMultiWordSuggestion<T>>();
		}

		return suggestions.add(o);
	}



	/**
	 * @param o
	 * @return
	 * @see java.util.List#remove(java.lang.Object)
	 */
	public boolean remove(Object o)
	{
		if ( suggestions != null)
		{
			return suggestions.remove(o);
		}

		return false;
	}

}
